package com.tanhua.server.service;

import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserFreeze;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitors;
import com.tanhua.dubbo.api.db.UserFreezeApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.CommentApi;
import com.tanhua.dubbo.api.mongo.PublishApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.VisitorsApi;
import com.tanhua.server.interceptors.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import com.tanhua.vo.Movements;
import com.tanhua.vo.PageResult;
import com.tanhua.vo.TodayBest;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.log4j.Logger;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MovementsService {

    @Reference
    private PublishApi publishApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private UserFreezeApi userFreezeApi;

    @Autowired
    private OssTemplate ossTemplate;


    @Reference
    private CommentApi commentApi;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    //保存圈子动态
    public ResponseEntity saveMovements(Publish publish, MultipartFile[]  imageContent) throws Exception {

        publish.setUserId(UserHolder.getUserId()); //指定这个动态是谁发布的
        //判断这个用户是否被冻结发布动态
        Long userId = publish.getUserId();
        UserFreeze userFreeze= userFreezeApi.findById(userId);
        if (userFreeze!=null) {
            if(userFreeze.getFreezingRange()==3){
                return ResponseEntity.ok(null);

            }
        }

        List<String> midieas = new ArrayList<>();
        for (MultipartFile image : imageContent) {
            String imageUrl = ossTemplate.upload(image.getOriginalFilename(), image.getInputStream());
            midieas.add(imageUrl);
        }
        publish.setMedias(midieas);


//        这个直接调用dubbo的api就可以了
        String publishId = publishApi.saveMovements(publish);

//        发送MQ消息
        rocketMQTemplate.convertAndSend("tanhua-publish",publishId);
        return ResponseEntity.ok(null);


    }
    //查询好友的圈子动态
    public ResponseEntity queryFriendMovements(Integer page, Integer pagesize) {
//       返回的是PageResult   查询当前登录人好友的动态
      PageResult pageResult = publishApi.queryFriendMovements(page,pagesize,UserHolder.getUserId());
        List<Publish> publishList = (List<Publish>) pageResult.getItems();
//        把publishList中的一个一个的Publish转成一个一个的Movements


        List<Movements> movementsList = new ArrayList<>();
        for (Publish publish : publishList) {
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
//            因为测试数据比较乱，所以有可能查不到用户
            if(userInfo==null){
                continue;
            }
            Movements movements = publishAndUserInfoToMovements(publish,userInfo);
            movementsList.add(movements);
        }
        pageResult.setItems(movementsList);
        return ResponseEntity.ok(pageResult);
    }

    //查询推荐的圈子动态
    public ResponseEntity queryRecommendMovements(Integer page, Integer pagesize) {

//        优先查大数据推荐，大数据推荐的是在redis
        PageResult pageResult = findPublishFromBigData(page,pagesize);
        if(pageResult==null){
 //                如果没有再从mongo中获取
            pageResult = publishApi.queryRecommendMovements(page,pagesize,UserHolder.getUserId());
        }
        //       返回的是PageResult   查询当前登录人推荐的动态
        List<Publish> publishList = (List<Publish>) pageResult.getItems();
//        把publishList中的一个一个的Publish转成一个一个的Movements
        List<Movements> movementsList = new ArrayList<>();
        for (Publish publish : publishList) {
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
//            因为测试数据比较乱，所以有可能查不到用户
            if(userInfo==null){
                continue;
            }
            Movements movements = publishAndUserInfoToMovements(publish,userInfo);
            movementsList.add(movements);
        }
        pageResult.setItems(movementsList);
        return ResponseEntity.ok(pageResult);
    }

//    优先查大数据推荐，大数据推荐的是在redis
    private PageResult findPublishFromBigData(Integer page, Integer pagesize) {
        Long userId = UserHolder.getUserId();
//        21,4,26,20,10064,3,10020,100093,22,6  目前默认推荐了10个，但是实际情况下不止10个
        String publishIdsStr = redisTemplate.boundValueOps("QUANZI_PUBLISH_RECOMMEND_" + userId).get();
//        QUANZI_PUBLISH_RECOMMEND_19
//        判断这个用户是否有推荐的数据
        if(StringUtils.isNotBlank(publishIdsStr)){
            String[] publishIdsArray = publishIdsStr.split(",");
//          publishIdsArray=[1,4,26,20,10064,3,10020,100093,22,6]
            int count = publishIdsArray.length; //这个数组的长度，就是分页查询需要的总条数
//            准备一个集合
            List<Publish> list = new ArrayList<>();
            int start = (page-1)*pagesize;

            if(start>count){ //如果起始位置超过了数组的总长度
                return null;
            }
            int end = page*pagesize;
            if(end>count){ //如果end的值超过了总长度 就把总长度的值赋给end
                end = count;
            }

            for (int i = start; i < end; i++) {
                String s = publishIdsArray[i];
                Publish publish = publishApi.findByPid(Long.parseLong(publishIdsArray[i]));
                list.add(publish);
            }
            return new PageResult(page,pagesize,count,list);
        }else{
//            当前登录人没有大数据推荐的圈子数据
            return null;
        }
    }


    //    提取出来的公共的代码：把publish和UserInfo转成movements
    private Movements publishAndUserInfoToMovements(Publish publish, UserInfo userInfo) {
        Movements movements = new Movements();
        BeanUtils.copyProperties(userInfo, movements);
        if (userInfo.getTags() != null) {
            movements.setTags(userInfo.getTags().split(","));
        }
        BeanUtils.copyProperties(publish, movements);
        movements.setId(publish.getId().toString());
        movements.setImageContent(publish.getMedias().toArray(new String[]{}));
        movements.setDistance("500米");
        movements.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

        if(redisTemplate.hasKey("quanzi_publish_like_"+UserHolder.getUserId()+"_"+publish.getId().toString())){
            movements.setHasLiked(1); //代表当前登录人对这个动态已点赞
        }else{
            movements.setHasLiked(0); //代表当前登录人对这个动态未点赞
        }

        if(redisTemplate.hasKey("quanzi_publish_love_"+UserHolder.getUserId()+"_"+publish.getId().toString())){
            movements.setHasLoved(1); //代表当前登录人对这个动态已喜欢
        }else{
            movements.setHasLoved(0); //代表当前登录人对这个动态未喜欢
        }

        return movements;
    }

    public ResponseEntity queryMySelfMovements(Integer page, Integer pagesize, Long userId) {
        if(userId==null){
            userId = UserHolder.getUserId();
        }
        //       返回的是PageResult   查询当前登录人自己的动态
        PageResult pageResult = publishApi.queryMySelfMovements(page,pagesize,userId);
        List<Publish> publishList = (List<Publish>) pageResult.getItems();
//        把publishList中的一个一个的Publish转成一个一个的Movements
        List<Movements> movementsList = new ArrayList<>();
        UserInfo userInfo = userInfoApi.findById(userId);// 当前登录人的信息
        for (Publish publish : publishList) {
            if(publish.getState()!=1){
                continue;
            }
            Movements movements = publishAndUserInfoToMovements(publish,userInfo);
            movementsList.add(movements);
        }
        pageResult.setItems(movementsList);
        return ResponseEntity.ok(pageResult);


    }



    public ResponseEntity likeComment(String publishId,Integer pubType) {
        Long userId = UserHolder.getUserId();

        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(1);  //评论类型，1-点赞，2-评论，3-喜欢
        comment.setPubType(pubType);    //评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setContent(""); //这是点赞的操作，所以评论内容是空的
        comment.setUserId(userId);
        //返回的是这个圈子动态的点赞数量
        Integer count = commentApi.save(comment);
//        当前登录人已对这个动态点赞了 记录到redis中
        redisTemplate.boundValueOps("quanzi_publish_like_"+userId+"_"+publishId).set("");
        return ResponseEntity.ok(count);

    }

    public ResponseEntity dislikeComment(String publishId, int pubType) {
        Long userId = UserHolder.getUserId();

        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(1);  //评论类型，1-点赞，2-评论，3-喜欢
        comment.setPubType(pubType);    //评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setContent(""); //这是点赞的操作，所以评论内容是空的
        comment.setUserId(userId);
        //返回的是这个圈子动态的点赞数量
        Integer count = commentApi.remove(comment);

        redisTemplate.delete("quanzi_publish_like_"+userId+"_"+publishId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity loveComment(String publishId, int pubType) {
        Long userId = UserHolder.getUserId();

        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);  //评论类型，1-点赞，2-评论，3-喜欢
        comment.setPubType(pubType);    //评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setContent(""); //这是点赞的操作，所以评论内容是空的
        comment.setUserId(userId);
        //返回的是这个圈子动态的点赞数量
        Integer count = commentApi.save(comment);
//        当前登录人已对这个动态点赞了 记录到redis中
        redisTemplate.boundValueOps("quanzi_publish_love_"+userId+"_"+publishId).set("");
        return ResponseEntity.ok(count);
    }

    public ResponseEntity unloveComment(String publishId, int pubType) {
        Long userId = UserHolder.getUserId();

        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(3);  //评论类型，1-点赞，2-评论，3-喜欢
        comment.setPubType(pubType);    //评论内容类型： 1-对圈子动态操作 2-对视频操作 3-对评论操作
        comment.setContent(""); //这是点赞的操作，所以评论内容是空的
        comment.setUserId(userId);
        //返回的是这个圈子动态的点赞数量
        Integer count = commentApi.remove(comment);

        redisTemplate.delete("quanzi_publish_love_"+userId+"_"+publishId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity queryMovementsById(String publishId) {
       Publish publish = publishApi.findById(publishId);
        Long userId = publish.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        Movements movements = publishAndUserInfoToMovements(publish, userInfo);
        return ResponseEntity.ok(movements);
    }

    @Reference
    private VisitorsApi visitorsApi;
    @Reference
    private RecommendUserApi recommendUserApi;
    public ResponseEntity queryVisitors() {
//        查询当前登录人的 被访问记录   获取上一次查看来访记录的时间节点
        Long userId = UserHolder.getUserId();
        String visitorTime = redisTemplate.boundValueOps("VISITOR_TIME_"+userId).get();
        List<Visitors> list = new ArrayList<>();
        if(visitorTime==null){
          list =  visitorsApi.queryVisitors(userId,5);
        }else{
          list =  visitorsApi.queryVisitors(userId,Long.parseLong(visitorTime),5);
        }

//        把一个一个的Visitors转成TodayBest
        TodayBest todayBest = null;
        List<TodayBest> todayBestList = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = userInfoApi.findById(visitors.getVisitorUserId());
            if(userInfo==null){
                continue;
            }
            todayBest = new TodayBest();
            BeanUtils.copyProperties(userInfo,todayBest);
            if(userInfo.getTags()!=null){
                todayBest.setTags(userInfo.getTags().split(",")); //就是从UserInfo中 但是UserInfo中的tags是字符串这里要的是数据
            }

            Long score = recommendUserApi.queryScore(userId, visitors.getVisitorUserId());
            todayBest.setFateValue(score); //缘分值
            todayBestList.add(todayBest);
        }


//        每次查看后需要把这个时间再记录到redis中
        redisTemplate.boundValueOps("VISITOR_TIME_"+userId).set(new Date().getTime()+"");

        return ResponseEntity.ok(todayBestList);

    }
}
